package com.smartlbs.baseframe.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.xml.XMLSerializer;

import com.alibaba.fastjson.JSON;
import com.smartlbs.util.DESUtil;
import com.smartlbs.util.HttpTookit;
import com.smartlbs.util.MD5Util;
import com.smartlbs.util.StringUtil;

/**
 * 微信工具类
 * 
 * 
 *
 */
public class WeChatUtils {

	//
	private static String ANDROID_APP_ID = "";
	private static String ANDROID_APP_SECRECT = "";
	private static String IOS_APP_ID = "";
	private static String IOS_APP_SECRECT = "";
	//商户信息
	private static String MCH_ID = "";
	private static String APP_KEY = "";
	//回调接口
	private static String CALLBACK_METHOD = "";
	
	//
	static{
		ConfigFileUtils.PROPERTY_PATH = "configs/wechat/wechat.properties";
		
		/*
		 * 获取属性值
		 */
		ANDROID_APP_ID = ConfigFileUtils.getPropertyString("Andorid_App_Id");
		ANDROID_APP_SECRECT = ConfigFileUtils.getPropertyString("Andorid_App_Security");
		IOS_APP_ID = ConfigFileUtils.getPropertyString("Ios_App_Id");
		IOS_APP_SECRECT = ConfigFileUtils.getPropertyString("Ios_App_Security");
		MCH_ID = ConfigFileUtils.getPropertyString("Mch_Id");
		APP_KEY = ConfigFileUtils.getPropertyString("App_Key");
		CALLBACK_METHOD = ConfigFileUtils.getPropertyString("Callback_Method");
	}
	
	/**
	 * 微信认证
	 * 
	 * 
	 * 
	 * @param code
	 * @return
	 * @throws Exception
	 */
	public static Map getOpenId(String code,int os) throws Exception {
		//请求路径
		//String postUrl = "https://api.weixin.qq.com/sns/jscode2session?grant_type=authorization_code";
		String postUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
		//参数对象
		Map<String, String> paramObj = new HashMap<String, String>();
		
		switch(os){
			case 1://ios
				paramObj.put("appid", IOS_APP_ID);
				paramObj.put("secret", IOS_APP_SECRECT);
			break;
			case 2://android
				paramObj.put("appid", ANDROID_APP_ID);
				paramObj.put("secret", ANDROID_APP_SECRECT);
			break;
		}
		
		//paramObj.put("js_code", code);
		paramObj.put("code", code);
		paramObj.put("grant_type", "authorization_code");
		//
		Map map = HttpTookit.getHttp(postUrl, paramObj, null, false, "UTF-8");
	
		Map accessTokenData = JSON.parseObject(map.get("data").toString(), Map.class);

		return accessTokenData;
	}

	/**
	 * 获取用户信息
	 * 
	 * 
	 * 
	 * @param code
	 * @return
	 * @throws Exception
	 */
	public static Map getUserInfo(String openId, String accessToken) throws Exception {
		//请求路径
		//String postUrl = "https://api.weixin.qq.com/cgi-bin/user/info";
		String postUrl = "https://api.weixin.qq.com/sns/userinfo";
		//参数对象
		Map<String, String> paramObj = new HashMap<String, String>();
		
		paramObj.put("openid", openId);
		paramObj.put("access_token", accessToken);
		paramObj.put("lang", "zh_CN");
		//
		Map map = HttpTookit.getHttp(postUrl, paramObj, null, false, "UTF-8");
	
		Map accessTokenData = JSON.parseObject(map.get("data").toString(), Map.class);

		return accessTokenData;
	}
	
	/**
	 * 统一下单
	 * 
	 * 
	 * @param openId
	 * @param fee
	 * @return
	 * @throws Exception
	 */
	public static Map unifiedOrder(String openId, long userId, Double fee, int os) throws Exception {
		//请求路径
		String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		
		//随机字符串
		String nonceStr = System.currentTimeMillis()+"";
		//唯一标识
		String tradeNo = userId+"-"+nonceStr+(100 + (int)(Math.random() * 999));
		Map<String,String> paramMap = new HashMap<String,String>();
		
		switch(os){
			case 1://ios
				paramMap.put("appid", IOS_APP_ID);
			break;
			case 2://android
				paramMap.put("appid", ANDROID_APP_ID);
			break;
		}
		paramMap.put("mch_id", MCH_ID);
		paramMap.put("body", "wechat-order"+nonceStr);
		paramMap.put("device_info", "WEB");
		paramMap.put("nonce_str", nonceStr);
		//paramMap.put("out_trade_no", MD5Util.getMD5Value("wechat-order"+tradeNo));
		paramMap.put("out_trade_no", tradeNo);
		paramMap.put("total_fee", ((int)(fee*100))+"");
		paramMap.put("trade_type", "APP");
		//
		paramMap.put("notify_url", CALLBACK_METHOD);
		paramMap.put("openid", openId);
		
		String sign = getWebMD5Sign(paramMap);
		//放入签名
		paramMap.put("sign", sign);
		
		//xml格式请求字符串
		String xmlRequestParam = formatXmlMap(paramMap);

		Map resultMap = HttpTookit.postHttp(url, xmlRequestParam, null, true, "UTF-8");

		//
		String xmlStringObj = resultMap.get("data").toString();
		XMLSerializer xmlSerializer = new XMLSerializer();  
		net.sf.json.JSON jsonObj = xmlSerializer.read(xmlStringObj);  
		
		Map returnMap=JSON.parseObject(jsonObj.toString(), Map.class);
		//请求成功，生成前端签名
		if(returnMap.get("result_code").toString().equals("SUCCESS")){
			paramMap.clear();
			switch(os){
				case 1://ios
					paramMap.put("appid", IOS_APP_ID);
				break;
				case 2://android
					paramMap.put("appid", ANDROID_APP_ID);
				break;
			}
			paramMap.put("partnerid", MCH_ID);
			paramMap.put("prepayid", returnMap.get("prepay_id").toString());
			paramMap.put("noncestr", returnMap.get("nonce_str").toString());
			paramMap.put("timestamp", nonceStr);
			paramMap.put("package", "Sign=WXPay");
			
			//加入时间戳
			returnMap.put("timestamp", getWebMD5Sign(paramMap));
			//加入新签名
			returnMap.put("sign", nonceStr);
		}
		
		return returnMap;
	}
	
	/**
	 * 获取签名
	 * 
	 * 
	 * 
	 * @param paramMap
	 * @return
	 * @throws Exception
	 */
	public static String getWebMD5Sign(Map<String, String> paramMap) throws Exception {
		//标签
		String stringA = formatUrlMap(paramMap);
		//
		String stringSignTemp=stringA+"&key="+APP_KEY;
		//
		String sign = MD5Util.getMD5Value(stringSignTemp).toUpperCase();
		
		return sign;
	}
	
	//获取请求xml字符串
	private static String formatXmlMap(Map<String, String> paramMap) throws Exception{
		//
		List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(paramMap.entrySet());  
	           
       // 构造URL 键值对的格式  
       StringBuffer buffer = new StringBuffer();
       
       //
       buffer.append("<xml>");
       
       for(Map.Entry<String, String> item : infoIds){
    	   if (!StringUtil.containEmpty(item.getKey())){  
    		   String key = item.getKey();  
    		   String val = item.getValue();
    		   
    		   buffer.append("<"+key+">");
    		   buffer.append(val);
    		   buffer.append("</"+key+">");
    		}
       }
       
       //
       buffer.append("</xml>");
       //
       return buffer.toString();
	}

	
	//获取标签字符串
	private static String formatUrlMap(Map<String, String> paraMap) throws Exception{
		//
		List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(paraMap.entrySet());  
	           
		// 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）  
		Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>(){
			@Override
			public int compare(Map.Entry<String, String> string1, Map.Entry<String, String> string2){
				return (string1.getKey()).toString().compareTo(string2.getKey());
			}
		}); 
	           
       // 构造URL 键值对的格式  
       StringBuffer buffer = new StringBuffer();
       
       for(Map.Entry<String, String> item : infoIds){
    	   if (!StringUtil.containEmpty(item.getKey())){  
    		   String key = item.getKey();  
    		   String val = item.getValue();  
    		   buffer.append(key + "=" + val);  
    		   buffer.append("&");
    		}
       }
       
       String result = buffer.toString();
       
       if(!StringUtil.containEmpty(result)){
    	   result = result.substring(0, result.length() - 1);
       }
       
       return result;
	}
	
	public static void main(String[] args) {
		try {
			String code = "081Hbf161xhBXS1D1s261k3m161Hbf1L";
			Map map = WeChatUtils.getOpenId(code,1);
			System.out.println(map);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
